package com.yhy.common.excel.utils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.export.styler.AbstractExcelExportStyler;
import cn.afterturn.easypoi.excel.export.styler.IExcelExportStyler;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.poi.ss.usermodel.*;
import org.springframework.http.HttpHeaders;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * Excel工具类 - EasyPoi
 */
@Slf4j
@UtilityClass
public class EasyPoiUtil {

    private final ThreadLocal<StopWatch> invokeTime = new ThreadLocal<>();
    private static final String XLSX_SUFFIX = ".xlsx";

    @SneakyThrows(value = UnsupportedEncodingException.class)
    public void exportExcel(HttpServletResponse response, List<?> dataList, String fileName, String sheetName) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        String name = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + name + XLSX_SUFFIX);
        response.setHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.ms-excel");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());

        ExportParams exportParams = new ExportParams();
        exportParams.setSheetName(StrUtil.isBlank(sheetName) ? fileName : sheetName);
        exportParams.setStyle(ExcelExportTitleStyle.class);
        exportParams.setType(ExcelType.XSSF); // 后缀.xlsx

        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, dataList.get(0).getClass(), dataList);
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 关闭输出Servlet流
        IoUtil.close(outputStream);
        stopWatch.start();
        log.info("导出excel耗时: {}毫秒", stopWatch.getTime());
    }

    public String generateExcel(List<?> dataList, String fileName, String sheetName) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ExportParams exportParams = new ExportParams();
        exportParams.setSheetName(StrUtil.isBlank(sheetName) ? fileName : sheetName);
        exportParams.setStyle(ExcelExportTitleStyle.class);
        exportParams.setType(ExcelType.XSSF); // 后缀.xlsx
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, dataList.get(0).getClass(), dataList);

        FileOutputStream outputStream = null;
        String path = "./" + fileName + XLSX_SUFFIX;
        try {
            outputStream = new FileOutputStream(path);
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 关闭输出Servlet流
        IoUtil.close(outputStream);
        stopWatch.stop();
        log.info("生成excel耗时: {}毫秒", stopWatch.getTime());
        return path;
    }

    @SneakyThrows(value = Exception.class)
    @SuppressWarnings("unchecked")
    public <T> List<T> importExcel(MultipartFile file, Class<T> targetType) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ImportParams importParams = new ImportParams();
        importParams.setTitleRows(0);
        importParams.setHeadRows(1);
        final T target = ReflectUtil.newInstanceIfPossible(targetType);
        List<Object> list = ExcelImportUtil.importExcelMore(file.getInputStream(), target.getClass(), importParams).getList();
        stopWatch.stop();
        log.info("解析excel耗时: {}毫秒", stopWatch.getTime());
        return (List<T>) list;
    }

    public class ExcelExportTitleStyle extends AbstractExcelExportStyler implements IExcelExportStyler {

        public ExcelExportTitleStyle(Workbook workbook) {
            super.createStyles(workbook);
        }

        @Override
        public CellStyle getTitleStyle(short color) {
            CellStyle titleStyle = workbook.createCellStyle();
            // 自定义字体
            Font font = workbook.createFont();
            font.setColor(IndexedColors.WHITE1.getIndex());
            font.setBold(true);
            font.setFontName("宋体");
            titleStyle.setFont(font);

            // 自定义背景色
            titleStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
            titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

            titleStyle.setBorderBottom(BorderStyle.THIN);
            titleStyle.setBorderTop(BorderStyle.THIN);
            titleStyle.setBorderLeft(BorderStyle.THIN);
            titleStyle.setBorderRight(BorderStyle.THIN);

            titleStyle.setAlignment(HorizontalAlignment.CENTER);
            titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            titleStyle.setWrapText(true);
            return titleStyle;
        }

        @Override
        public CellStyle stringSeptailStyle(Workbook workbook, boolean isWarp) {
            CellStyle style = workbook.createCellStyle();
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            style.setDataFormat(STRING_FORMAT);
            if (isWarp) {
                style.setWrapText(true);
            }
            return style;
        }

        @Override
        public CellStyle getHeaderStyle(short color) {
            CellStyle titleStyle = workbook.createCellStyle();
            Font font = workbook.createFont();
            font.setFontHeightInPoints((short) 20);
            titleStyle.setFont(font);
            titleStyle.setAlignment(HorizontalAlignment.CENTER);
            titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            return titleStyle;
        }

        @Override
        public CellStyle stringNoneStyle(Workbook workbook, boolean isWarp) {
            CellStyle style = workbook.createCellStyle();
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            style.setDataFormat(STRING_FORMAT);
            if (isWarp) {
                style.setWrapText(true);
            }
            return style;
        }

    }

}

